home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
lang
/
mc302
/
dosutil
/
calc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-03-18
|
6KB
|
222 lines
/*
* A very simple 16-bit TSR (POP-UP) calculator, featuring automatic entry
* of last result into DOS applications. This feature works only on AT or
* higher class machines with a recent BIOS.
*
* Use 'calc' with no operands for NON-TSR operation.
*
* If HOTKEYS are specified on the command line, CALC will install
* itself as a TSR (Ram-Resident) program, which can be invoked at
* any time by pressing the HOTKEYS. Available HOTKEYS are:
* L - Left SHIFT
* R - Right SHIFT
* A - ALT
* C - CONTROL
* S - SysRq (Caution: some systems may not like this one)
*
* eg: CALC LR (Install with LEFT+RIGHT SHIFT for hotkeys)
*
* Keys used:
* + Addition
* - Subtraction
* * Multiply
* / Divide
* % Modulus
* & Bitwise AND
* | Bitwise OR
* ^ Bitwise EXCLUSIVE OR
* < Shift left
* > Shift right
* = Display result
* 0-9 Decimal input digits
* A-F Hexidecimal input digits
* 'c Enter a single ASCII character value
* "cc Enter a dual ASCII character value
* K Clear display
* R Read value from memory
* S Store value in memory
* BKSP Clear last digit
* SPACE Toggle HEX/DECIMAL
* ESC Exit, no entry
* ENTER Exit, enter value to DOS application (works only on AT or higher)
* UP Move display up
* DOWN Move display down
* RIGHT Move display right
* LEFT Move display left
*
* Copyright 1990-1994 Dave Dunfield
* All rights reserved.
*
* Permission granted for personal (non-commercial) use only.
*
* Compile command: cc calc -fop
*/
#include <stdio.h>
#include <window.h>
#include <tsr.h>
int x=33, y=10, acc = 0, acc1, memory = 0;
char op, mode = 0;
/* Scan codes for entered digit values */
char scans[] = {
0x0B, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0A, 0x1E, 0x30, 0x2E, 0x20, 0x12, 0x21 };
/*
* Main calculator program
*/
calc()
{
char c, buffer[7];
op = acc ? '=' : ' '; /* Use '=' reset mode if value left over */
redraw:
wopen(x, y, 9, 4, (WSAVE|WBOX2|WCOPEN|WSCROLL)+REVERSE);
wcursor_off();
for(;;) {
wprintf(mode ? "\r%c $%04x" : "\r%c%6d", op, acc);
switch(c = toupper(wgetc())) {
case '+' : /* Record all operators */
case '-' :
case '*' :
case '/' :
case '%' :
case '&' :
case '|' :
case '^' :
case '<' :
case '>' :
doeval();
wprintf(mode ? "\r $%04x\n" : "\r %6d\n", acc1);
acc = 0;
op = c;
break;
case '=' : /* Display partial result */
doeval();
wclwin();
acc = acc1;
op = '=';
break;
case '\'' : /* Single ASCII character */
acc = wgetc();
break;
case '"' : /* Double ASCII character */
acc = (wgetc() << 8) | wgetc();
break;
case _KBS : /* Delete last entered digit */
acc /= mode ? 16 : 10;
break;
case _KUA : /* Move display up */
if(y) --y;
goto move;
case _KDA : /* Move display down */
if(y < 21) ++y;
goto move;
case _KLA : /* Move display left */
if(x) --x;
goto move;
case _KRA : /* Move display right */
if(x < 71)
++x;
move:
wclose();
goto redraw;
case ' ' : /* Toggle hex/decmal mode */
mode = !mode;
break;
case '\n' : /* Exit and enter value */
doeval();
sprintf(buffer, mode ? "%x" : "%d", acc = acc1);
for(acc1 = 0; c = buffer[acc1]; ++acc1)
pushkey(c, scans[c]);
wclose();
return;
case '\x1B' : /* Exit and don't enter value */
doeval();
acc = acc1;
wclose();
return;
case 'K' : /* Clear the calculator display */
acc = acc1 = 0;
op = ' ';
break;
case 'S' : /* Save to memory */
memory = acc;
break;
case 'R' : /* Restore from memory */
acc = memory;
break;
default:
if(op == '=') { /* Previous result to clear */
acc = acc1 = 0;
op = ' '; }
if(mode) { /* Hex input */
if(isdigit(c))
acc = (acc * 16) + (c - '0');
else if((c >= 'A') && (c <= 'F'))
acc = (acc * 16) + (c - ('A'-10)); }
else if(isdigit(c)) /* Decimal input */
acc = (acc * 10) + (c - '0'); } }
}
/*
* Evaluate the last recorded operation
*/
doeval()
{
switch(op) {
case '+' : acc1 += acc; break;
case '-' : acc1 -= acc; break;
case '*' : acc1 *= acc; break;
case '/' : if(!acc) goto dbz; acc1 /= acc; break;
case '%' : if(!acc) goto dbz; acc1 %= acc; break;
case '&' : acc1 &= acc; break;
case '|' : acc1 |= acc; break;
case '^' : acc1 ^= acc; break;
case '<' : acc1 <<=acc; break;
case '>' : acc1 >>=acc; break;
default : acc1 = acc; break;
dbz: wprintf("\n? / 0\nError"); wgetc(); }
}
/*
* Shove a key (char & scancode) into the BIOS keyboard buffer
*/
pushkey(c, s) asm
{
MOV CH,4[BP] ; Get Scan code
MOV CL,6[BP] ; Get character
MOV AH,05h ; Push key...
INT 16h ; Ask BIOS
}
/*
* Main program, either TSR or execute main tty program menu
*/
main(argc, argv)
int argc;
int *argv[];
{
int hot_keys;
char *ptr;
/* If RAM-resident, print startup message & TSR */
if(argc > 1) {
fputs("POP-UP Calculator\n\nCopyright 1990-1994 Dave Dunfield\nAll rights reserved.", stderr);
hot_keys = 0;
ptr = argv[1];
while(*ptr) switch(toupper(*ptr++)) {
case 'A' : hot_keys |= ALT; break;
case 'C' : hot_keys |= CONTROL; break;
case 'L' : hot_keys |= L_SHIFT; break;
case 'R' : hot_keys |= R_SHIFT; break;
case 'S' : hot_keys |= SYS_REQ; break;
default: abort("\n\nInvalid HOTKEY"); }
tsr(&calc, hot_keys, 2000); }
/* Not RAM-resident, execute the program */
calc();
}